package net

import (
	"fmt"
	"net"
	"sync"
)

type TcpServer struct {
	localPort int
	localIp   string

	running bool

	l net.Listener

	dataArrival       func(clientId string, data []byte)
	clientConnected   func(clientId string, c net.Conn)
	clientStateChange func(clientId string, state ConnectState)

	clients map[string]net.Conn

	mutex sync.Mutex
}

// Start 启动服务
// localIp 本机ip,如果全部IP则传入空字符串,例如：0.0.0.0
// localPort 本机端口
func (s *TcpServer) Start(localIp string, localPort int) error {
	listen, err := net.Listen("tcp", fmt.Sprintf("%v:%v", localIp, localPort))
	if err != nil {
		return err
	}
	s.l = listen
	s.running = true
	s.clients = make(map[string]net.Conn)
	go func() {
		for s.running {
			accept, err2 := s.l.Accept()
			if err2 == nil {
				if s.clientConnected != nil {
					clientId := fmt.Sprintf("%v-%v", accept.LocalAddr().String(), accept.RemoteAddr().String())
					s.clientConnected(clientId, accept)
					s.mutex.Lock()
					s.clients[clientId] = accept
					s.mutex.Unlock()
					go s.dealClient(clientId, accept)
				}
			}
		}
	}()
	return nil
}

// Stop 停止服务
func (s *TcpServer) Stop() {
	s.running = false
	if s.l != nil {
		_ = s.l.Close()
	}
	s.l = nil
	//close all client
	if s.clients != nil {
		s.mutex.Lock()
		defer s.mutex.Unlock()
		for k, v := range s.clients {
			_ = v.Close()
			if s.clientStateChange != nil {
				go s.clientStateChange(k, Disconnected)
			}
			delete(s.clients, k)
		}
	}
}

// OnDataArrival 数据到达回调
// clientId 客户端id
// data 数据
func (s *TcpServer) OnDataArrival(f func(clientId string, data []byte)) {
	s.dataArrival = f
}

func (s *TcpServer) OnClientConnected(f func(clientId string, conn net.Conn)) {
	s.clientConnected = f
}

// OnClientStateChange 客户端状态变化回调
// clientId 客户端id
// client 客户端
// state 状态
func (s *TcpServer) OnClientStateChange(f func(clientId string, state ConnectState)) {
	s.clientStateChange = f
}

// Send 发送数据到客户端
// clientId 客户端编码
// data:发送数据
func (s *TcpServer) Send(clientId string, data []byte) (int, error) {
	conn, ok := s.clients[clientId]
	if !ok {
		return 0, fmt.Errorf("当前服务中不存在[%v]的客户端", clientId)
	}
	n, err := conn.Write(data)
	return n, err
}

func (s *TcpServer) Close(cid string) {
	conn, ok := s.clients[cid]
	if ok {
		_ = conn.Close()
		s.mutex.Lock()
		defer s.mutex.Unlock()
		delete(s.clients, cid)
	}
}

func (s *TcpServer) dealClient(cid string, c net.Conn) {
	d := make([]byte, 4096)
	for s.running {
		n, err := c.Read(d)
		if err != nil {
			s.mutex.Lock()
			delete(s.clients, cid)
			s.mutex.Unlock()
			_ = c.Close()
			if s.clientStateChange != nil {
				go s.clientStateChange(cid, Disconnected)
			}
			break
		}
		if s.dataArrival != nil {
			s.dataArrival(cid, d[:n])
		}
	}
}
